﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Resources;
using SAPbouiCOM;
using System.Reflection;
using System.Collections;
using System.Xml.Serialization;
using System.IO;
using System.Xml;

namespace BoAddonBiz_FreightForwarder
{
    /*
     * 资源文件规则如下：
     * 配置信息统一放到Config.resx下，键以窗体名称+下划线作为前缀，输入的key不需要加入上述前缀
     * 信息统一放在语言名称+下划线+Message.resx下，键同样是窗体名称+下划线作为前缀，输入的key不需要加入上述前缀
     */

    #region memo
    /*
     * 原计划是用单件避免ResourceManager的频繁实例化
     * 但是ResourceManager不能反应编译后动态修改的资源文件内容
     * 因为资源文件将自动被编译成DLL，嵌入在项目中，由于是被预先编译的，所以效率高。 
     * 如果是在 VS.NET 中添加的 .resx 文件，会自动被设为 Embedded Resource，转成 .resources 文件后被嵌入到 Assembly 中。
     * 所以需要用ResXResourceReader
     * 如果ResXResourceReader是用流模式读取的话，单件不单件的没什么意义
     */
    #endregion
    /// <summary>
    /// 单件，避免频繁实例化ResourceManager
    /// </summary>
    /// <author>Webb.Wen</author>
    /// <lastedit>2011-07-28 10:03:27</lastedit>
    public sealed class B1ResourceManager
    {
        /// <summary>
        /// 获取资源文件信息模板
        /// </summary>
        /// <param name="form">调用的窗体，通常传入this即可</param>
        /// <param name="Language">当前系统语言</param>
        /// <param name="key">资源文件键，方法会自动补充“窗体名称+下划线”</param>
        /// <returns>String.Format的format模板</returns>
        public string GetMessageFormat(SAPBoAddon.B1Form form, BoLanguages Language, string key)
        {
            //BoAddonBiz_FreightForwarder.Resource.ln_Chinese_Message.B1Form_ConditionTemplete_CanNotBeNull
            string resourcename = String.Format(@"Resource\{0}_Message.resx", Language.ToString());
            string resourcekey = String.Format("{0}_{1}", form.GetType().Name, key);

            using (System.Resources.ResXResourceReader reader = new ResXResourceReader(resourcename))
            {
                foreach (DictionaryEntry entry in reader)
                {
                    if (entry.Key.ToString() == resourcekey)
                    {
                        return entry.Value as string;
                    }
                }
            }
            throw new Exception(String.Format("资源文件“{0}”中不能找到键“{1}”的值", resourcename, resourcekey));
        }
        /// <summary>
        /// 从资源文件中获取配置信息
        /// </summary>
        /// <param name="form">调用的窗体，通常传入this即可</param>
        /// <param name="key">资源文件键，方法会自动补充“窗体名称+下划线”</param>
        /// <returns>资源文件中配置好的值</returns>
        public string GetConfig(SAPBoAddon.B1Form form, string key)
        {
            string resourcekey = String.Format("{0}_{1}", form.GetType().Name, key);
            using (System.Resources.ResXResourceReader reader = new ResXResourceReader(@"Resource\Config.resx"))
            {
                foreach (DictionaryEntry entry in reader)
                {
                    if (entry.Key.ToString() == resourcekey)
                    {
                        return entry.Value as string;
                    }
                }
            }
            throw new Exception(String.Format("资源文件“{0}”中不能找到键“{1}”的值", "Config.resx", resourcekey));
        }
        /// <summary>
        /// 获取资源文件键值对（资源文件名称和窗体名称一致）
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        public Dictionary<string, string> GetResourceKeyValues(string resxname)
        {
            /*这里不一定要读取资源文件，可以读取任意格式化数据，用资源文件只是我的习惯*/
            Dictionary<string, string> keyvalues = new Dictionary<string, string>();
            using (System.Resources.ResXResourceReader reader = new ResXResourceReader( String.Format(@"{0}\Resource\{1}.resx",System.Windows.Forms.Application.StartupPath, resxname)))
            {
                foreach (DictionaryEntry entry in reader)
                {
                    keyvalues.Add(entry.Key.ToString(), entry.Value.ToString());
                }
            }
            return keyvalues;
        }

        public string SerializeDictionary(Dictionary<string, string> dic)
        {
            List<KeyValue> kvs = new List<KeyValue>();
            foreach (var item in dic)
            {
                //KeyValue kv = new KeyValue();
                //kv.Key = item.Key;
                //kv.Value = item.Value;
                //kvs.Add(kv);
                kvs.Add(new KeyValue() { Key = item.Key, Value = item.Value });
            }

            //XmlSerializer ser = new XmlSerializer(typeof(KeyValue[]));
            //System.IO.MemoryStream mem = new MemoryStream();
            //XmlTextWriter writer = new XmlTextWriter(mem, Encoding.UTF8);
            //ser.Serialize(writer, kvs.ToArray());
            //writer.Close();

            //string xml = Encoding.UTF8.GetString(mem.ToArray());

            string xml = new ObjectToXML<KeyValue[]>().FromObjectToXML(kvs.ToArray());
            return xml;
        }
        public Dictionary<string, string> DeserializeDictionary(string xml)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            KeyValue[] kvs = new ObjectToXML<KeyValue[]>().FromXMLToObject(xml);
            for (int i = 0; i < kvs.Length; i++)
            {
                dic.Add(kvs[i].Key, kvs[i].Value);
            }
            return dic;
        }

        B1ResourceManager()
        {

        }

        public static B1ResourceManager GetInstance()
        {
            return Nested.instance;
        }

        class Nested
        {
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static Nested()
            {
            }
            internal static readonly B1ResourceManager instance = new B1ResourceManager();
        }
    }
    [Serializable]
    public class KeyValue
    {
        string _key;
        public string Key
        {
            get { return _key; }
            set { _key = value; }
        }
        string _value;
        public string Value
        {
            get { return _value; }
            set { _value = value; }
        }
    }
    /// <summary>
    /// 范型类，用于对象（数组）和序列化的XML字符串之间的相互转换
    /// </summary>
    /// <typeparam name="ObjectType">指定的对象类型</typeparam>
    public class ObjectToXML<ObjectType>
    {
        /// <summary>
        /// 从对象（数组）转换成XML序列字符串
        /// </summary>
        /// <param name="obj">要转换的对象（数组）</param>
        /// <returns>XML序列字符串</returns>
        public string FromObjectToXML(ObjectType obj)
        {
            try
            {
                if (obj == null)
                    return null;

                XmlSerializer x = new XmlSerializer(obj.GetType());
                StringBuilder sb = new StringBuilder();
                StringWriter sw = new StringWriter(sb);
                x.Serialize(sw, obj);
                string s = sb.ToString();
                sw.Close();
                return s;
            }
            catch (Exception ex)
            {
                return null;
            }

        }
        /// <summary>
        /// 从XML字符串反序列化成对象（数组）
        /// </summary>
        /// <param name="s">要反序列化的XML字符串</param>
        /// <returns>对象（数组）</returns>
        public ObjectType FromXMLToObject(string s)
        {
            if (s == "" || s == null)
                return default(ObjectType);

            StringReader sr = new StringReader(s);
            XmlSerializer x = new XmlSerializer(typeof(ObjectType));
            ObjectType lc = (ObjectType)(x.Deserialize(sr));
            return lc;
        }

    }
}
